package de.unibi.comet.tools;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import de.unibi.comet.fa.GeneralizedString;
import de.unibi.comet.fa.PrositeMotifParser;
import de.unibi.comet.util.Log;

public class empirical_dist {

	public static void usage() {
		System.out.println("usage: empirical_dist <motif> <random_texts> <maxmass> <overlapping>");
		System.out.println(" <overlapping>: \"O\" for overlapping, \"N\" for non-overlapping"); 
		System.exit(1);
	}

	public static int naiveMatch(String s, List<GeneralizedString> pl) {
		int matches=0;
		for (int i=0; i<s.length(); ++i) {
			for (GeneralizedString pattern : pl) {
				if (pattern.matches(s, i)) {
					matches+=1;
					// System.out.println(String.format("m %d (%s)", i+pattern.length()-1, s.substring(i, i+pattern.length())));
				}
			}
		}
		return matches;
	}

	private static class LengthComparator implements Comparator<GeneralizedString> {
		public int compare(GeneralizedString o1, GeneralizedString o2) {
			if (o1.length()<o2.length()) return -1;
			if (o1.length()>o2.length()) return 1;
			return 0;
		}
	}
	
	public static int naiveMatchNoOverlaps(String s, List<GeneralizedString> pl) {
		int matches=0;
		ArrayList<GeneralizedString> sortedList = new ArrayList<GeneralizedString>(pl);
		Collections.sort(sortedList, new LengthComparator());
		for (int i=0; i<s.length(); ++i) {
			for (GeneralizedString pattern : sortedList) {
				if (pattern.matches(s, i)) {
					matches+=1;
					// System.out.println(String.format("m %d (%s)", i+pattern.length()-1, s.substring(i, i+pattern.length())));
					// System.out.println(String.format("m %d", i+pattern.length()-1));
					i+=pattern.length()-1;
					break;
				}
			}
		}
		return matches;
	}
	
	public static void main(String[] args) {
//		List<GeneralizedString> stringList = PrositeMotifParser.parse("A-x(1,2)-A");
//		naiveMatchNoOverlaps("AAAACA",stringList);
//		System.exit(0);
		
		if (args.length!=4) usage();
		String motif = args[0];
		int maxMass = Integer.parseInt(args[2]);
		boolean overlapsAllowed = true;
		if (args[3].equals("O")||args[3].equals("N")) {
			overlapsAllowed=(args[3].equals("O"));
		} else {
			usage();
		}
	
		int n = 0;
		int[] dist = new int[maxMass+1];

		Log.getInstance().setTimingActive(true);
		Log.getInstance().setLogLevel(Log.Level.INSANE);

		List<GeneralizedString> stringList = null;
		System.out.println(String.format("pattern:\"%s\"",motif));
		try {
			stringList = PrositeMotifParser.parse(motif);
			// System.out.println(l.size());
		} catch (IllegalArgumentException e) {
			System.out.println(String.format("invalid :\"%s\"",motif));
			return;
		}
	
		FileInputStream patternFile = null;
		try {
			patternFile = new FileInputStream(args[1]);
		} catch (FileNotFoundException e) {
			System.out.println("File not found, sorry!");
			System.exit(1);
		}
		BufferedReader br = new BufferedReader(new InputStreamReader(patternFile));
		try {
			while (true) {
				String line = br.readLine();
				if (line==null) break;
				// int matches = naiveMatch(line, stringList);
				int matches = overlapsAllowed?naiveMatch(line, stringList):naiveMatchNoOverlaps(line, stringList);
				if (matches>maxMass) matches=maxMass;
				dist[matches]+=1;
				++n;
			}
		} catch (IOException e) {
			System.out.println("I/O failure, sorry!");
			System.exit(1);
		}
		
		StringBuffer sb = new StringBuffer();
		for (int mass=0; mass<=maxMass; ++mass) {
			sb.append(String.format("%e | ", ((double)dist[mass])/n));
		}
		System.out.println(sb.toString());		
	}
}
